package com.meeruu.sg.account.core.domain.facade.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.meeruu.common.model.page.PageResult;
import com.meeruu.common.utils.LoggerUtil;
import com.meeruu.common.utils.mapper.OrikaMapperUtils;
import com.meeruu.sg.account.core.api.constant.AccountGroup;
import com.meeruu.sg.account.core.api.constant.AccountType;
import com.meeruu.sg.account.core.api.constant.PlatformType;
import com.meeruu.sg.account.core.api.dto.request.query.*;
import com.meeruu.sg.account.core.api.dto.response.*;
import com.meeruu.sg.account.core.api.exception.ErrorCode;
import com.meeruu.sg.account.core.api.service.IAccountQueryService;
import com.meeruu.sg.account.core.domain.biz.AccountQueryBiz;
import com.meeruu.sg.account.core.domain.mapper.AccountDayEndMapper;
import com.meeruu.sg.account.core.domain.model.AccountDayEndDO;
import com.meeruu.sg.account.core.domain.model.FundRequestRecordDO;
import com.meeruu.sg.account.core.domain.service.FundRequestRecordService;
import com.meeruu.sg.account.core.domain.util.AssertUtils;
import com.meeruu.summerframework.cloud.anno.MRSCProvider;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Auther: liwu
 * @Date: 2019/5/15 18:21
 * @Description:
 */
@Slf4j
@MRSCProvider(serviceInterface = IAccountQueryService.class)
@Component
public class AccountQueryServiceImpl implements IAccountQueryService {


    @Autowired
    private AccountQueryBiz accountQueryBiz;

    @Autowired
    private FundRequestRecordService fundRequestRecordService;

    @Resource
    private AccountDayEndMapper accountDayEndMapper;


    @Override
    public List<AccountType> getAccountTypeByAccountGroup(AccountGroup accountGroup) {

        LoggerUtil.info(log, "根据账户组别查询账户类型开始,param accountGroup: %s", accountGroup);
        AssertUtils.isTrue(StringUtils.isEmpty(accountGroup), ErrorCode.PARAM_ERROR.getCode(), "accountGroup 不能为空");

        return accountQueryBiz.getAccountType(accountGroup);
    }

    @Override
    public List<? extends AccountResponseDTO> listAccounts(ListAccountQueryDTO listAccountQueryRequest) {
        AssertUtils.isTrue(listAccountQueryRequest == null
                || listAccountQueryRequest.getAccountGroup() == null
                || listAccountQueryRequest.getAccountGroup() == null
                || StringUtils.isEmpty(listAccountQueryRequest.getUserCode()), ErrorCode.PARAM_ERROR.getCode(), "参数错误");
        return accountQueryBiz.listAccounts(listAccountQueryRequest.getAccountGroup(), listAccountQueryRequest.getAccountType(), listAccountQueryRequest.getUserCode());
    }

    @Override
    public List<? extends AccountResponseDTO> listAccountsByIds(ListAccountByIdsQueryDTO listAccountQueryRequest) {
        AssertUtils.isTrue(listAccountQueryRequest == null
                || listAccountQueryRequest.getAccountGroup() == null
                || listAccountQueryRequest.getAccountGroup() == null
                || CollectionUtils.isEmpty(listAccountQueryRequest.getAccountIds()), ErrorCode.PARAM_ERROR.getCode(), "参数错误");
        return accountQueryBiz.listAccounts(listAccountQueryRequest.getAccountGroup(), listAccountQueryRequest.getAccountType(), listAccountQueryRequest.getAccountIds());
    }

    @Override
    public AccountResponseDTO getAccountByAccountId(String accountId, AccountGroup accountGroup) {

        LoggerUtil.info(log, "根据账户ID查询请求开始,param accountId: %s ,accountGroup: %s", accountId, accountGroup);

        AssertUtils.isTrue(StringUtils.isEmpty(accountId), ErrorCode.PARAM_ERROR.getCode(), "accountId 不能为空");
        AssertUtils.isTrue(StringUtils.isEmpty(accountGroup), ErrorCode.PARAM_ERROR.getCode(), "accountGroup 不能为空");

        return accountQueryBiz.getAccount(accountId, accountGroup);
    }

    @Override
    public UserAccountResponseDTO getUserAccountByUserCodeAndAccountType(String userCode, AccountType accountType) {

        LoggerUtil.info(log, "根据 userCode,accountType 查询请求开始,param userCode: %s ,accountType: %s", userCode, accountType);

        AssertUtils.isTrue(StringUtils.isEmpty(userCode), ErrorCode.PARAM_ERROR.getCode(), "userCode 不能为空");
        AssertUtils.isTrue(StringUtils.isEmpty(accountType), ErrorCode.PARAM_ERROR.getCode(), "accountType 不能为空");
        return accountQueryBiz.getUserAccountByUserCodeAndAccountType(userCode, accountType);
    }

    @Override
    public Map<Integer, UserAccountResponseDTO> getUserAccounts(String userCode) {
        LoggerUtil.info(log, "根据 userCode 查询请求开始,param userCode: %s ", userCode);

        AssertUtils.isTrue(StringUtils.isEmpty(userCode), ErrorCode.PARAM_ERROR.getCode(), "userCode 不能为空");
        List<UserAccountQueryDTO> queryDTOS = new ArrayList<>();
        Arrays.stream(AccountType.values()).forEach(accountType -> {
            queryDTOS.add(new UserAccountQueryDTO(userCode, accountType));
        });
        List<UserAccountResponseDTO> userAccounts = accountQueryBiz.getUserAccountGroup(queryDTOS);
        return userAccounts.stream().collect(Collectors.toMap(s -> s.getAccountType().getCode(), x -> x, (a, b) -> b));
    }


    @Override
    public List<UserAccountResponseDTO> getUserAccountGroup(List<UserAccountQueryDTO> queryDTOS) {
        AssertUtils.isTrue(null == queryDTOS, ErrorCode.PARAM_ERROR.getCode(), "查询条件不能为空");
        queryDTOS.forEach(tmp -> {
            AssertUtils.isTrue(StringUtils.isEmpty(tmp.getUserCode()), ErrorCode.PARAM_ERROR.getCode(), "userCode 不能为空");
            AssertUtils.isTrue(StringUtils.isEmpty(tmp.getAccountType()), ErrorCode.PARAM_ERROR.getCode(), "accountType 不能为空");
        });

        return accountQueryBiz.getUserAccountGroup(queryDTOS);

    }


    @Override
    public MerchantAccountResponseDTO getMerchantAccountByMerchantCodeAndAccountType(String merchantCode, AccountType accountType) {

        LoggerUtil.info(log, "根据 merchantCode,accountType 查询请求开始,param merchantCode: %s ,accountType: %s", merchantCode, accountType);

        AssertUtils.isTrue(StringUtils.isEmpty(merchantCode), ErrorCode.PARAM_ERROR.getCode(), "merchantCode 不能为空");
        AssertUtils.isTrue(StringUtils.isEmpty(accountType), ErrorCode.PARAM_ERROR.getCode(), "accountType 不能为空");
        return accountQueryBiz.getMerchantAccountByMerchantCodeAndAccountType(merchantCode, accountType);
    }

    @Override
    public PageResult<WholeAccountResponseDTO> getAccountPage(AccountQueryFilterDTO filter) {

        LoggerUtil.info(log, "分页查询账户记录信息开始,param:{}", filter);

        AssertUtils.isTrue(null == filter, ErrorCode.PARAM_ERROR.getCode(), "filter信息不能为空");

        return accountQueryBiz.getAccountPage(filter);
    }


    @Override
    public OrgAccountResponseDTO getOrgAccountByName(String name) {
        OrgAccountResponseDTO orgAccount = accountQueryBiz.getOrgAccountByName(name);
        return orgAccount;
    }

    @Override
    public List<FundRequestRecordDTO> getFundRequestRecord(String outBizNo, PlatformType platformType, Integer status) {
        AssertUtils.isTrue(StringUtils.isEmpty(outBizNo), ErrorCode.PARAM_ERROR.getCode(), "outBizNo信息不能为空");

        List<Integer> statusGroup = new ArrayList<>();
        statusGroup.add(status);

        PlatformType resultType = platformType == null ? PlatformType.SG : platformType;
        List<FundRequestRecordDO> queryList = fundRequestRecordService.selectByOutBizNoAndPlatformType(outBizNo, resultType.getCode(), statusGroup);
        return OrikaMapperUtils.mapList(queryList, FundRequestRecordDO.class, FundRequestRecordDTO.class);
    }

    @Override
    public List<KanBanResponseDTO> kanbanStatistics(Integer accountGroup) {

        return accountQueryBiz.kanbanStatistics(AccountGroup.getByCode(accountGroup));
    }

    @Override
    public PageResult<AccountDayEndDTO> accountDayEndQueryPage(AccountDayEndQueryPageDTO param) {
        PageHelper.startPage(param.getPage(), param.getPageSize());
        List<AccountDayEndDO> result = accountDayEndMapper.query(param.getAccountType(), param.getStartTime(), param.getEndTime());
        Page pageList = (Page) result;
        List<AccountDayEndDTO> response = OrikaMapperUtils.mapList(pageList.getResult(), AccountDayEndDO.class, AccountDayEndDTO.class);
        PageResult<AccountDayEndDTO> pageResponse = new PageResult<>(param.getPage(), param.getPageSize(), pageList.getTotal());
        pageResponse.setData(response);
        return pageResponse;
    }

    @Override
    public List<AccountDayEndDTO> accountDayEndQuery(AccountDayEndQueryPageDTO param) {
        List<AccountDayEndDO> result = accountDayEndMapper.query(param.getAccountType(), param.getStartTime(), param.getEndTime());
        return OrikaMapperUtils.mapList(result, AccountDayEndDO.class, AccountDayEndDTO.class);
    }

}
